package com.springcloud.gateway.exception;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
import org.springframework.cloud.gateway.support.NotFoundException;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.result.view.ViewResolver;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 网关全局异常处理器
 * 处理网关层的各类异常，返回统一的错误响应
 */
@Component
@Order(-1)
public class GlobalExceptionHandler implements ErrorWebExceptionHandler {
    
    private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
    
    private List<ViewResolver> viewResolvers = Collections.emptyList();
    private ServerCodecConfigurer serverCodecConfigurer;
    
    public void setViewResolvers(List<ViewResolver> viewResolvers) {
        this.viewResolvers = viewResolvers;
    }
    
    public void setMessageWriters(List<?> messageWriters) {
        // 保留方法以支持配置
    }
    
    public void setMessageReaders(List<?> messageReaders) {
        // 保留方法以支持配置
    }
    
    public void setServerCodecConfigurer(ServerCodecConfigurer serverCodecConfigurer) {
        this.serverCodecConfigurer = serverCodecConfigurer;
    }

    @Override
    public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
        logger.error("网关异常: {}", ex.getMessage(), ex);

        ServerHttpResponse response = exchange.getResponse();
        response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
        
        // 设置默认状态码和错误信息
        HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR;
        String errorCode = "500";
        String errorMessage = "网关服务内部错误";
        
        // 根据不同异常类型设置不同的状态码和错误信息
        if (ex instanceof NotFoundException) {
            status = HttpStatus.NOT_FOUND;
            errorCode = "404";
            errorMessage = "请求的资源不存在";
        } else if (ex instanceof org.springframework.cloud.gateway.support.TimeoutException) {
            status = HttpStatus.GATEWAY_TIMEOUT;
            errorCode = "504";
            errorMessage = "服务响应超时";
        } else if (ex instanceof org.springframework.cloud.gateway.support.ServerWebExchangeBindException) {
            status = HttpStatus.BAD_REQUEST;
            errorCode = "400";
            errorMessage = "请求参数错误";
        }
        
        response.setStatusCode(status);
        
        // 构建错误响应内容
        Map<String, Object> errorResponse = new HashMap<>();
        errorResponse.put("code", errorCode);
        errorResponse.put("message", errorMessage);
        errorResponse.put("path", exchange.getRequest().getPath());
        errorResponse.put("timestamp", System.currentTimeMillis());
        
        // 将错误响应写入响应体
        return response.writeWith(
            Mono.just(response.bufferFactory().wrap(
                com.alibaba.fastjson.JSON.toJSONBytes(errorResponse)
            ))
        );
    }
}